###libraries
library(tidyverse)
library(dplyr)
library(ggplot2)
library(tidyheatmaps)
library(reshape2)
library(RColorBrewer)
library(vegan)
library(FactoMineR)
library(pheatmap)
library(viridis)
library(tidyheatmaps)
setwd("C:/Users/Owner/Desktop/Project-Howler/R-humaan")
path <- read.table("pathabundance-cmp.tsv" , header = TRUE , sep = '\t')
path
NA
path <- path[!grepl("UNINTEGRATED", path$Pathway), ]
path <- path[!grepl("UNMAPPED", path$Pathway), ]
# Display the updated dataframe
head(path)
NA
### to normalize the data
#relative abundances
# Store genus names
path_names <- path[,1]
# Convert the numerical data to matrix for normalization
numerical_data <- as.matrix(path[,-1]) # exclude first column but keep it stored
# Normalize
normalized_data <- sweep(numerical_data, 2, colSums(numerical_data), '/')
normalized_data <- normalized_data * 100
# Create final dataframe with genus names
final_path <- data.frame(path_names, normalized_data)
colnames(final_path ) <- gsub("\\.", "-", colnames(final_path ))
write.table(final_path , "final_path.txt ", sep = "\t" , row.names = FALSE, quote = FALSE)
final_path
NA
NA
path_data <- read.table("final_path.txt" , header = TRUE , sep = '\t')
colnames(path_data) <- gsub("\\.", "-", colnames(path_data))
metadata <- read.csv("howlermeta.csv") # Replace with your actual file name
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) :
invalid first argument
Error in assign(cacheKey, frame, .rs.CachedDataEnv) :
attempt to use zero-length variable name
path_data
metadata
NA
NA
##clean and merge
path_long <- path_data %>%
pivot_longer(cols = -path_names, names_to = "SampleID", values_to = "Abundance")
path_long$SampleID <- gsub("_Abundance", "", path_long$SampleID)
path_long
# Merge with metadata
tidy_data <- merge(path_long, metadata, by="SampleID")
tidy_data
NA
# Calculate relative abundance
path_long_normalized <- path_long %>%
group_by(SampleID) %>%
mutate(RelativeAbundance = Abundance / sum(Abundance)) %>%
ungroup()
# Merge with metadata
tidy_data <- merge(path_long_normalized, metadata, by="SampleID")
# Show the first few rows of the final dataset
print(head(tidy_data))
# Calculate mean relative abundance for each pathway
top_pathways <- tidy_data %>%
group_by(path_names) %>%
summarize(
mean_abundance = mean(RelativeAbundance),
sd_abundance = sd(RelativeAbundance)
) %>%
arrange(desc(mean_abundance)) %>%
head(10)
# Print the top 10 pathways
print(top_pathways)
# Create a visualization of top 10 pathways
library(ggplot2)
# Simplify pathway names for better visualization
top_pathways$short_names <- gsub("^([^:]+:)\\s*(.+?)\\|.*$", "\\1\
\\2", top_pathways$path_names)
# Create the plot
ggplot(top_pathways, aes(x = reorder(short_names, mean_abundance), y = mean_abundance)) +
geom_bar(stat = "identity", fill = "steelblue") +
geom_errorbar(aes(ymin = mean_abundance - sd_abundance,
ymax = mean_abundance + sd_abundance),
width = 0.2) +
coord_flip() +
theme_minimal() +
labs(x = "Pathway",
y = "Mean Relative Abundance",
title = "Top 10 Most Abundant Pathways") +
theme(axis.text.y = element_text(size = 8))

NA
NA
t# Let's get the actual top 10 pathways without splitting by the classification
function (x)
UseMethod("t")
<bytecode: 0x000002839b3d4ca8>
<environment: namespace:base>
top_10_pathways <- tidy_data %>%
# First split the path_names to get the base pathway name
mutate(base_pathway = sub("\\|.*$", "", path_names)) %>%
group_by(base_pathway) %>%
summarize(
total_abundance = mean(RelativeAbundance)
) %>%
arrange(desc(total_abundance)) %>%
head(10)
print("Top 10 base pathways:")
[1] "Top 10 base pathways:"
print(top_10_pathways)
# Now create the heatmap matrix with these pathways
heatmap_matrix <- tidy_data %>%
# Create the base pathway column
mutate(base_pathway = sub("\\|.*$", "", path_names)) %>%
# Filter for top 10 base pathways
filter(base_pathway %in% top_10_pathways$base_pathway) %>%
# Sum abundances for the same base pathway
group_by(base_pathway, SampleID) %>%
summarize(RelativeAbundance_Percent = sum(RelativeAbundance) * 100, .groups = "drop") %>%
# Create the matrix
pivot_wider(names_from = SampleID,
values_from = RelativeAbundance_Percent) %>%
as.data.frame()
# Convert row names
row_names <- heatmap_matrix$base_pathway
heatmap_matrix <- heatmap_matrix[,-1]
rownames(heatmap_matrix) <- row_names
# Convert to matrix
heatmap_matrix <- as.matrix(heatmap_matrix)
# Create annotation data frame for samples
annotation_col <- metadata %>%
select(SampleID, Season, Sex) %>%
column_to_rownames("SampleID")
# Update the colors to include all seasons
ann_colors <- list(
Season = c(Rain = "#2166AC", Intermediate = "#B2182B", Dry = "#4DAF4A"),
Sex = c(Male = "#4DAF4A", Female = "#FF7F00")
)
# Create the heatmap
p2 <- pheatmap(heatmap_matrix,
scale = "none", # Don't scale since we already have percentages
cluster_rows = TRUE,
cluster_cols = TRUE,
annotation_col = annotation_col,
annotation_colors = ann_colors,
color = viridis::magma(10), # Ensure the color palette is correctly specified
border_color = "black",
fontsize_row = 8,
fontsize_col = 8,
angle_col = 45,
main = "Top 10 Pathways Relative Abundance (%)",
display_numbers = FALSE,
number_format = "%.2f",
)

ggsave("Heatmap of Top 10 Most Abundant PW.jpg", plot = p2, width = 10, height = 8, dpi = 300)
library(tibble)
# Retry transforming data to wide format
wide_data <- tidy_data %>%
select(SampleID, path_names, RelativeAbundance) %>%
pivot_wider(names_from = path_names, values_from = RelativeAbundance, values_fill = 0) %>%
column_to_rownames(var = "SampleID")
# Calculate Bray-Curtis dissimilarity matrix
bray_curtis_matrix <- vegdist(wide_data, method = "bray")
# Convert to regular matrix and display first few rows/columns
bc_matrix <- as.matrix(bray_curtis_matrix)
bc_matrix
# Save the full matrix to a file
write.csv(as.matrix(bray_curtis_matrix), "bray_curtis_matrix_humaan.csv")
# Perform PCoA using the Bray-Curtis dissimilarity matrix
# bray_curtis_matrix <- bray_curtis_matrix[,-1]
pcoa_result <- cmdscale(bc_matrix, eig = TRUE, k = 2)
# Create a dataframe for plotting
pcoa_df <- data.frame(
PCoA1 = pcoa_result$points[,1],
PCoA2 = pcoa_result$points[,2],
Season = metadata$Season,
Individual = metadata$Individual
)
pcoa_points <- data.frame(
SampleID = rownames(wide_data),
PCo1 = pcoa_result$points[,1],
PCo2 = pcoa_result$points[,2]
)
# Calculate variance explained
variance_explained <- round(100 * pcoa_result$eig / sum(pcoa_result$eig), 2)
# Merge with metadata
pcoa_data <- merge(pcoa_points, metadata, by="SampleID")
# Plot PCoA results by Season
p1 <- ggplot(pcoa_df, aes(x = PCoA1, y = PCoA2, color = Season)) +
geom_point(size = 3, alpha = 0.6) +
theme_minimal() +
labs(
title = "PCoA of Gut Microbiome PW by Season",
x = "PCoA1",
y = "PCoA2"
) +
stat_ellipse(level = 0.95)
# Plot PCoA results by Individual
p2 <- ggplot(pcoa_df, aes(x = PCoA1, y = PCoA2, color = Individual)) +
geom_point(size = 3, alpha = 0.6) +
theme_minimal() +
labs(
title = "PCoA of Gut Microbiome PW by Individual",
x = "PCoA1",
y = "PCoA2"
)
# Print plots
print(p1)

print(p2)

# Correct the order of months starting from October
month_levels <- c("October", "November", "December", "January", "February", "March", "April", "May", "June", "July", "August", "September")
# Ensure Month is a factor with the correct levels
pcoa_data$Month <- factor(pcoa_data$Month, levels = month_levels)
pcoa_data_pathway <- pcoa_data[order(pcoa_data$Individual, pcoa_data$Month), ]
pcoa_data_pathway$PCo1_diff <- ave(pcoa_data_pathway$PCo1, pcoa_data_pathway$Individual,
FUN=function(x) c(NA, diff(x)))
# Recreate the plot with simplified months
p_temporal_clean <- ggplot(pcoa_data, aes(x=Month, y=PCo1, color=Individual, group=Individual)) +
geom_line(linewidth=1, alpha=0.7) +
geom_point(size=3) +
theme_bw() +
labs(x="",
y="PCo1",
title="Temporal Changes in Gut Microbiome PW") +
theme(axis.text.x = element_text(angle = 45, hjust = 1),
panel.grid.minor = element_blank(),
panel.spacing = unit(2, "lines"),
strip.background = element_rect(fill="white"),
strip.text = element_text(size=12)) +
facet_wrap(~Individual, scales="free_y", ncol=2)
# Print the plot
print(p_temporal_clean)
# Calculate monthly statistics for each individual
monthly_stats <- aggregate(PCo1 ~ Month + Individual, data=pcoa_data,
FUN=function(x) c(mean=mean(x), sd=sd(x), n=length(x)))
# Convert the results to a more readable format
monthly_stats_df <- data.frame(
Month = monthly_stats$Month,
Individual = monthly_stats$Individual,
Mean_PCo1 = monthly_stats$PCo1[,1],
SD_PCo1 = monthly_stats$PCo1[,2],
N_samples = monthly_stats$PCo1[,3]
)
print("Monthly statistics by individual:")
[1] "Monthly statistics by individual:"
print(monthly_stats_df)
# Save the plot
ggsave("Temporal_changes_PW_monthly.pdf", plot = p_temporal_clean, width = 8, height = 12)

# Summarize the mean and SD of month-to-month differences for genus data
genus_summary <- aggregate(PCo1_diff ~ Individual, data=pcoa_data_genus,
FUN=function(x) c(mean=mean(abs(x), na.rm=TRUE),
sd=sd(abs(x), na.rm=TRUE)))
# Summarize the mean and SD of month-to-month differences for pathway data
pathway_summary <- aggregate(PCo1_diff ~ Individual, data=pcoa_data_pathway,
FUN=function(x) c(mean=mean(abs(x), na.rm=TRUE),
sd=sd(abs(x), na.rm=TRUE)))
# Extract mean differences for statistical comparison
genus_means <- sapply(genus_summary$PCo1_diff, `[`, 1)
pathway_means <- sapply(pathway_summary$PCo1_diff, `[`, 1)
# Perform a paired t-test
t_test_result <- t.test(genus_means, pathway_means, paired=TRUE)
print(t_test_result)
Paired t-test
data: genus_means and pathway_means
t = NaN, df = 13, p-value = NA
alternative hypothesis: true mean difference is not equal to 0
95 percent confidence interval:
NaN NaN
sample estimates:
mean difference
0
# If data is not normally distributed, use Wilcoxon signed-rank test
wilcox_test_result <- wilcox.test(genus_means, pathway_means, paired=TRUE)
Warning: cannot compute exact p-value with zeroes
print(wilcox_test_result)
Wilcoxon signed rank test with continuity correction
data: genus_means and pathway_means
V = 0, p-value = NA
alternative hypothesis: true location shift is not equal to 0
# Combine data for visualization
genus_summary$Dataset <- "Genus"
pathway_summary$Dataset <- "Pathway"
combined_summary <- rbind(genus_summary, pathway_summary)
# Boxplot of month-to-month differences
ggplot(combined_summary, aes(x=Dataset, y=PCo1_diff[,1], fill=Dataset)) +
geom_boxplot() +
labs(x="Dataset", y="Mean Month-to-Month Change in PCo1",
title="Comparison of Temporal Changes in PCo1") +
theme_minimal()

LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7cn0NCiMjI2xpYnJhcmllcw0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh0aWR5aGVhdG1hcHMpDQpsaWJyYXJ5KHJlc2hhcGUyKQ0KbGlicmFyeShSQ29sb3JCcmV3ZXIpDQpsaWJyYXJ5KHZlZ2FuKQ0KbGlicmFyeShGYWN0b01pbmVSKQ0KbGlicmFyeShwaGVhdG1hcCkNCmxpYnJhcnkodmlyaWRpcykNCmxpYnJhcnkodGlkeWhlYXRtYXBzKQ0KDQpgYGANCg0KYGBge3J9DQpzZXR3ZCgiQzovVXNlcnMvT3duZXIvRGVza3RvcC9Qcm9qZWN0LUhvd2xlci9SLWh1bWFhbiIpDQpwYXRoIDwtIHJlYWQudGFibGUoInBhdGhhYnVuZGFuY2UtY21wLnRzdiIgLCBoZWFkZXIgPSBUUlVFICwgc2VwID0gJ1x0JykNCnBhdGgNCg0KYGBgDQpgYGB7cn0NCnBhdGggPC0gcGF0aFshZ3JlcGwoIlVOSU5URUdSQVRFRCIsIHBhdGgkUGF0aHdheSksIF0NCnBhdGggPC0gcGF0aFshZ3JlcGwoIlVOTUFQUEVEIiwgcGF0aCRQYXRod2F5KSwgXQ0KDQojIERpc3BsYXkgdGhlIHVwZGF0ZWQgZGF0YWZyYW1lDQpoZWFkKHBhdGgpDQoNCmBgYA0KYGBge3J9DQojIyMgdG8gbm9ybWFsaXplIHRoZSBkYXRhIA0KDQojcmVsYXRpdmUgYWJ1bmRhbmNlcw0KDQojIFN0b3JlIGdlbnVzIG5hbWVzDQpwYXRoX25hbWVzIDwtIHBhdGhbLDFdDQoNCiMgQ29udmVydCB0aGUgbnVtZXJpY2FsIGRhdGEgdG8gbWF0cml4IGZvciBub3JtYWxpemF0aW9uDQpudW1lcmljYWxfZGF0YSA8LSBhcy5tYXRyaXgocGF0aFssLTFdKSAgIyBleGNsdWRlIGZpcnN0IGNvbHVtbiBidXQga2VlcCBpdCBzdG9yZWQNCg0KIyBOb3JtYWxpemUNCm5vcm1hbGl6ZWRfZGF0YSA8LSBzd2VlcChudW1lcmljYWxfZGF0YSwgMiwgY29sU3VtcyhudW1lcmljYWxfZGF0YSksICcvJykNCm5vcm1hbGl6ZWRfZGF0YSA8LSBub3JtYWxpemVkX2RhdGEgKiAxMDANCg0KIyBDcmVhdGUgZmluYWwgZGF0YWZyYW1lIHdpdGggZ2VudXMgbmFtZXMNCmZpbmFsX3BhdGggPC0gZGF0YS5mcmFtZShwYXRoX25hbWVzLCBub3JtYWxpemVkX2RhdGEpDQpjb2xuYW1lcyhmaW5hbF9wYXRoICkgPC0gZ3N1YigiXFwuIiwgIi0iLCBjb2xuYW1lcyhmaW5hbF9wYXRoICkpDQp3cml0ZS50YWJsZShmaW5hbF9wYXRoICAsICJmaW5hbF9wYXRoLnR4dCAiLCBzZXAgPSAiXHQiICwgcm93Lm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UpDQoNCmZpbmFsX3BhdGggDQoNCg0KYGBgDQpgYGB7cn0NCnBhdGhfZGF0YSA8LSByZWFkLnRhYmxlKCJmaW5hbF9wYXRoLnR4dCIgLCBoZWFkZXIgPSBUUlVFICwgc2VwID0gJ1x0JykNCmNvbG5hbWVzKHBhdGhfZGF0YSkgPC0gZ3N1YigiXFwuIiwgIi0iLCBjb2xuYW1lcyhwYXRoX2RhdGEpKQ0KDQoNCm1ldGFkYXRhIDwtIHJlYWQuY3N2KCJob3dsZXJtZXRhLmNzdiIpICAjIFJlcGxhY2Ugd2l0aCB5b3VyIGFjdHVhbCBmaWxlIG5hbWUNCnBhdGhfZGF0YQ0KbWV0YWRhdGENCg0KDQpgYGANCmBgYHtyfQ0KIyNjbGVhbiBhbmQgbWVyZ2UNCg0KDQpwYXRoX2xvbmcgPC0gcGF0aF9kYXRhICU+JQ0KICBwaXZvdF9sb25nZXIoY29scyA9IC1wYXRoX25hbWVzLCBuYW1lc190byA9ICJTYW1wbGVJRCIsIHZhbHVlc190byA9ICJBYnVuZGFuY2UiKQ0KDQpwYXRoX2xvbmckU2FtcGxlSUQgPC0gZ3N1YigiX0FidW5kYW5jZSIsICIiLCBwYXRoX2xvbmckU2FtcGxlSUQpDQpwYXRoX2xvbmcNCiMgTWVyZ2Ugd2l0aCBtZXRhZGF0YQ0KdGlkeV9kYXRhIDwtIG1lcmdlKHBhdGhfbG9uZywgbWV0YWRhdGEsIGJ5PSJTYW1wbGVJRCIpDQoNCg0KdGlkeV9kYXRhDQoNCmBgYA0KDQoNCmBgYHtyfQ0KIyBDYWxjdWxhdGUgcmVsYXRpdmUgYWJ1bmRhbmNlDQpwYXRoX2xvbmdfbm9ybWFsaXplZCA8LSBwYXRoX2xvbmcgJT4lDQogIGdyb3VwX2J5KFNhbXBsZUlEKSAlPiUNCiAgbXV0YXRlKFJlbGF0aXZlQWJ1bmRhbmNlID0gQWJ1bmRhbmNlIC8gc3VtKEFidW5kYW5jZSkpICU+JQ0KICB1bmdyb3VwKCkNCg0KIyBNZXJnZSB3aXRoIG1ldGFkYXRhDQp0aWR5X2RhdGEgPC0gbWVyZ2UocGF0aF9sb25nX25vcm1hbGl6ZWQsIG1ldGFkYXRhLCBieT0iU2FtcGxlSUQiKQ0KDQojIFNob3cgdGhlIGZpcnN0IGZldyByb3dzIG9mIHRoZSBmaW5hbCBkYXRhc2V0DQpwcmludChoZWFkKHRpZHlfZGF0YSkpDQpgYGANCg0KDQoNCg0KDQpgYGB7cn0NCiMgQ2FsY3VsYXRlIG1lYW4gcmVsYXRpdmUgYWJ1bmRhbmNlIGZvciBlYWNoIHBhdGh3YXkNCnRvcF9wYXRod2F5cyA8LSB0aWR5X2RhdGEgJT4lDQogIGdyb3VwX2J5KHBhdGhfbmFtZXMpICU+JQ0KICBzdW1tYXJpemUoDQogICAgbWVhbl9hYnVuZGFuY2UgPSBtZWFuKFJlbGF0aXZlQWJ1bmRhbmNlKSwNCiAgICBzZF9hYnVuZGFuY2UgPSBzZChSZWxhdGl2ZUFidW5kYW5jZSkNCiAgKSAlPiUNCiAgYXJyYW5nZShkZXNjKG1lYW5fYWJ1bmRhbmNlKSkgJT4lDQogIGhlYWQoMTApDQoNCiMgUHJpbnQgdGhlIHRvcCAxMCBwYXRod2F5cw0KcHJpbnQodG9wX3BhdGh3YXlzKQ0KDQojIENyZWF0ZSBhIHZpc3VhbGl6YXRpb24gb2YgdG9wIDEwIHBhdGh3YXlzDQpsaWJyYXJ5KGdncGxvdDIpDQoNCiMgU2ltcGxpZnkgcGF0aHdheSBuYW1lcyBmb3IgYmV0dGVyIHZpc3VhbGl6YXRpb24NCnRvcF9wYXRod2F5cyRzaG9ydF9uYW1lcyA8LSBnc3ViKCJeKFteOl0rOilcXHMqKC4rPylcXHwuKiQiLCAiXFwxXA0KXFwyIiwgdG9wX3BhdGh3YXlzJHBhdGhfbmFtZXMpDQoNCiMgQ3JlYXRlIHRoZSBwbG90DQpnZ3Bsb3QodG9wX3BhdGh3YXlzLCBhZXMoeCA9IHJlb3JkZXIoc2hvcnRfbmFtZXMsIG1lYW5fYWJ1bmRhbmNlKSwgeSA9IG1lYW5fYWJ1bmRhbmNlKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJzdGVlbGJsdWUiKSArDQogIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBtZWFuX2FidW5kYW5jZSAtIHNkX2FidW5kYW5jZSwgDQogICAgICAgICAgICAgICAgICAgIHltYXggPSBtZWFuX2FidW5kYW5jZSArIHNkX2FidW5kYW5jZSksIA0KICAgICAgICAgICAgICAgIHdpZHRoID0gMC4yKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnMoeCA9ICJQYXRod2F5IiwgDQogICAgICAgeSA9ICJNZWFuIFJlbGF0aXZlIEFidW5kYW5jZSIsDQogICAgICAgdGl0bGUgPSAiVG9wIDEwIE1vc3QgQWJ1bmRhbnQgUGF0aHdheXMiKSArDQogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkNCg0KDQpgYGANCmBgYHtyfQ0KdCMgTGV0J3MgZ2V0IHRoZSBhY3R1YWwgdG9wIDEwIHBhdGh3YXlzIHdpdGhvdXQgc3BsaXR0aW5nIGJ5IHRoZSBjbGFzc2lmaWNhdGlvbg0KdG9wXzEwX3BhdGh3YXlzIDwtIHRpZHlfZGF0YSAlPiUNCiAgIyBGaXJzdCBzcGxpdCB0aGUgcGF0aF9uYW1lcyB0byBnZXQgdGhlIGJhc2UgcGF0aHdheSBuYW1lDQogIG11dGF0ZShiYXNlX3BhdGh3YXkgPSBzdWIoIlxcfC4qJCIsICIiLCBwYXRoX25hbWVzKSkgJT4lDQogIGdyb3VwX2J5KGJhc2VfcGF0aHdheSkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICB0b3RhbF9hYnVuZGFuY2UgPSBtZWFuKFJlbGF0aXZlQWJ1bmRhbmNlKQ0KICApICU+JQ0KICBhcnJhbmdlKGRlc2ModG90YWxfYWJ1bmRhbmNlKSkgJT4lDQogIGhlYWQoMTApDQoNCnByaW50KCJUb3AgMTAgYmFzZSBwYXRod2F5czoiKQ0KcHJpbnQodG9wXzEwX3BhdGh3YXlzKQ0KDQojIE5vdyBjcmVhdGUgdGhlIGhlYXRtYXAgbWF0cml4IHdpdGggdGhlc2UgcGF0aHdheXMNCmhlYXRtYXBfbWF0cml4IDwtIHRpZHlfZGF0YSAlPiUNCiAgIyBDcmVhdGUgdGhlIGJhc2UgcGF0aHdheSBjb2x1bW4NCiAgbXV0YXRlKGJhc2VfcGF0aHdheSA9IHN1YigiXFx8LiokIiwgIiIsIHBhdGhfbmFtZXMpKSAlPiUNCiAgIyBGaWx0ZXIgZm9yIHRvcCAxMCBiYXNlIHBhdGh3YXlzDQogIGZpbHRlcihiYXNlX3BhdGh3YXkgJWluJSB0b3BfMTBfcGF0aHdheXMkYmFzZV9wYXRod2F5KSAlPiUNCiAgIyBTdW0gYWJ1bmRhbmNlcyBmb3IgdGhlIHNhbWUgYmFzZSBwYXRod2F5DQogIGdyb3VwX2J5KGJhc2VfcGF0aHdheSwgU2FtcGxlSUQpICU+JQ0KICBzdW1tYXJpemUoUmVsYXRpdmVBYnVuZGFuY2VfUGVyY2VudCA9IHN1bShSZWxhdGl2ZUFidW5kYW5jZSkgKiAxMDAsIC5ncm91cHMgPSAiZHJvcCIpICU+JQ0KICAjIENyZWF0ZSB0aGUgbWF0cml4DQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBTYW1wbGVJRCwgDQogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gUmVsYXRpdmVBYnVuZGFuY2VfUGVyY2VudCkgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQojIENvbnZlcnQgcm93IG5hbWVzDQpyb3dfbmFtZXMgPC0gaGVhdG1hcF9tYXRyaXgkYmFzZV9wYXRod2F5DQpoZWF0bWFwX21hdHJpeCA8LSBoZWF0bWFwX21hdHJpeFssLTFdDQpyb3duYW1lcyhoZWF0bWFwX21hdHJpeCkgPC0gcm93X25hbWVzDQoNCiMgQ29udmVydCB0byBtYXRyaXgNCmhlYXRtYXBfbWF0cml4IDwtIGFzLm1hdHJpeChoZWF0bWFwX21hdHJpeCkNCg0KIyBDcmVhdGUgYW5ub3RhdGlvbiBkYXRhIGZyYW1lIGZvciBzYW1wbGVzDQphbm5vdGF0aW9uX2NvbCA8LSBtZXRhZGF0YSAlPiUNCiAgc2VsZWN0KFNhbXBsZUlELCBTZWFzb24sIFNleCkgJT4lDQogIGNvbHVtbl90b19yb3duYW1lcygiU2FtcGxlSUQiKQ0KDQojIFVwZGF0ZSB0aGUgY29sb3JzIHRvIGluY2x1ZGUgYWxsIHNlYXNvbnMNCmFubl9jb2xvcnMgPC0gbGlzdCgNCiAgICBTZWFzb24gPSBjKFJhaW4gPSAiIzIxNjZBQyIsIEludGVybWVkaWF0ZSA9ICIjQjIxODJCIiwgRHJ5ID0gIiM0REFGNEEiKSwNCiAgICBTZXggPSBjKE1hbGUgPSAiIzREQUY0QSIsIEZlbWFsZSA9ICIjRkY3RjAwIikNCikNCg0KIyBDcmVhdGUgdGhlIGhlYXRtYXANCnAyIDwtIHBoZWF0bWFwKGhlYXRtYXBfbWF0cml4LA0KICAgICAgICAgc2NhbGUgPSAibm9uZSIsICAjIERvbid0IHNjYWxlIHNpbmNlIHdlIGFscmVhZHkgaGF2ZSBwZXJjZW50YWdlcw0KICAgICAgICAgY2x1c3Rlcl9yb3dzID0gVFJVRSwNCiAgICAgICAgIGNsdXN0ZXJfY29scyA9IFRSVUUsDQogICAgICAgICBhbm5vdGF0aW9uX2NvbCA9IGFubm90YXRpb25fY29sLA0KICAgICAgICAgYW5ub3RhdGlvbl9jb2xvcnMgPSBhbm5fY29sb3JzLA0KICAgICAgICAgY29sb3IgPSB2aXJpZGlzOjptYWdtYSgxMCksICAjIEVuc3VyZSB0aGUgY29sb3IgcGFsZXR0ZSBpcyBjb3JyZWN0bHkgc3BlY2lmaWVkDQogICAgICAgICBib3JkZXJfY29sb3IgPSAiYmxhY2siLA0KICAgICAgICAgZm9udHNpemVfcm93ID0gOCwNCiAgICAgICAgIGZvbnRzaXplX2NvbCA9IDgsDQogICAgICAgICBhbmdsZV9jb2wgPSA0NSwNCiAgICAgICAgIG1haW4gPSAiVG9wIDEwIFBhdGh3YXlzIFJlbGF0aXZlIEFidW5kYW5jZSAoJSkiLA0KICAgICAgICAgZGlzcGxheV9udW1iZXJzID0gRkFMU0UsDQogICAgICAgICBudW1iZXJfZm9ybWF0ID0gIiUuMmYiLA0KICAgICAgICAgKQ0KDQpnZ3NhdmUoIkhlYXRtYXAgb2YgVG9wIDEwIE1vc3QgQWJ1bmRhbnQgUFcuanBnIiwgcGxvdCA9IHAyLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSA4LCBkcGkgPSAzMDApDQoNCmBgYA0KYGBge3J9DQpsaWJyYXJ5KHRpYmJsZSkNCg0KIyBSZXRyeSB0cmFuc2Zvcm1pbmcgZGF0YSB0byB3aWRlIGZvcm1hdA0Kd2lkZV9kYXRhIDwtIHRpZHlfZGF0YSAlPiUNCiAgc2VsZWN0KFNhbXBsZUlELCBwYXRoX25hbWVzLCBSZWxhdGl2ZUFidW5kYW5jZSkgJT4lDQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBwYXRoX25hbWVzLCB2YWx1ZXNfZnJvbSA9IFJlbGF0aXZlQWJ1bmRhbmNlLCB2YWx1ZXNfZmlsbCA9IDApICU+JQ0KICBjb2x1bW5fdG9fcm93bmFtZXModmFyID0gIlNhbXBsZUlEIikNCg0KIyBDYWxjdWxhdGUgQnJheS1DdXJ0aXMgZGlzc2ltaWxhcml0eSBtYXRyaXgNCmJyYXlfY3VydGlzX21hdHJpeCA8LSB2ZWdkaXN0KHdpZGVfZGF0YSwgbWV0aG9kID0gImJyYXkiKQ0KDQojIENvbnZlcnQgdG8gcmVndWxhciBtYXRyaXggYW5kIGRpc3BsYXkgZmlyc3QgZmV3IHJvd3MvY29sdW1ucw0KYmNfbWF0cml4IDwtIGFzLm1hdHJpeChicmF5X2N1cnRpc19tYXRyaXgpDQpiY19tYXRyaXgNCiMgU2F2ZSB0aGUgZnVsbCBtYXRyaXggdG8gYSBmaWxlDQp3cml0ZS5jc3YoYXMubWF0cml4KGJyYXlfY3VydGlzX21hdHJpeCksICJicmF5X2N1cnRpc19tYXRyaXhfaHVtYWFuLmNzdiIpDQpgYGANCg0KYGBge3J9DQojIFBlcmZvcm0gUENvQSB1c2luZyB0aGUgQnJheS1DdXJ0aXMgZGlzc2ltaWxhcml0eSBtYXRyaXgNCiMgYnJheV9jdXJ0aXNfbWF0cml4IDwtIGJyYXlfY3VydGlzX21hdHJpeFssLTFdDQpwY29hX3Jlc3VsdCA8LSBjbWRzY2FsZShiY19tYXRyaXgsIGVpZyA9IFRSVUUsIGsgPSAyKQ0KDQojIENyZWF0ZSBhIGRhdGFmcmFtZSBmb3IgcGxvdHRpbmcNCnBjb2FfZGYgPC0gZGF0YS5mcmFtZSgNCiAgUENvQTEgPSBwY29hX3Jlc3VsdCRwb2ludHNbLDFdLA0KICBQQ29BMiA9IHBjb2FfcmVzdWx0JHBvaW50c1ssMl0sDQogIFNlYXNvbiA9IG1ldGFkYXRhJFNlYXNvbiwNCiAgSW5kaXZpZHVhbCA9IG1ldGFkYXRhJEluZGl2aWR1YWwNCikNCg0KcGNvYV9wb2ludHMgPC0gZGF0YS5mcmFtZSgNCiAgU2FtcGxlSUQgPSByb3duYW1lcyh3aWRlX2RhdGEpLA0KICBQQ28xID0gcGNvYV9yZXN1bHQkcG9pbnRzWywxXSwNCiAgUENvMiA9IHBjb2FfcmVzdWx0JHBvaW50c1ssMl0NCikNCg0KIyBDYWxjdWxhdGUgdmFyaWFuY2UgZXhwbGFpbmVkDQp2YXJpYW5jZV9leHBsYWluZWQgPC0gcm91bmQoMTAwICogcGNvYV9yZXN1bHQkZWlnIC8gc3VtKHBjb2FfcmVzdWx0JGVpZyksIDIpDQoNCiMgTWVyZ2Ugd2l0aCBtZXRhZGF0YQ0KcGNvYV9kYXRhIDwtIG1lcmdlKHBjb2FfcG9pbnRzLCBtZXRhZGF0YSwgYnk9IlNhbXBsZUlEIikNCg0KIyBQbG90IFBDb0EgcmVzdWx0cyBieSBTZWFzb24NCnAxIDwtIGdncGxvdChwY29hX2RmLCBhZXMoeCA9IFBDb0ExLCB5ID0gUENvQTIsIGNvbG9yID0gU2Vhc29uKSkgKw0KICBnZW9tX3BvaW50KHNpemUgPSAzLCBhbHBoYSA9IDAuNikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlBDb0Egb2YgR3V0IE1pY3JvYmlvbWUgUFcgYnkgU2Vhc29uIiwNCiAgICB4ID0gIlBDb0ExIiwNCiAgICB5ID0gIlBDb0EyIg0KICApICsNCiAgc3RhdF9lbGxpcHNlKGxldmVsID0gMC45NSkNCg0KIyBQbG90IFBDb0EgcmVzdWx0cyBieSBJbmRpdmlkdWFsDQpwMiA8LSBnZ3Bsb3QocGNvYV9kZiwgYWVzKHggPSBQQ29BMSwgeSA9IFBDb0EyLCBjb2xvciA9IEluZGl2aWR1YWwpKSArDQogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGFscGhhID0gMC42KSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUENvQSBvZiBHdXQgTWljcm9iaW9tZSBQVyBieSBJbmRpdmlkdWFsIiwNCiAgICB4ID0gIlBDb0ExIiwNCiAgICB5ID0gIlBDb0EyIg0KICApDQoNCiMgUHJpbnQgcGxvdHMNCnByaW50KHAxKQ0KcHJpbnQocDIpDQoNCmBgYA0KYGBge3J9DQojIENvcnJlY3QgdGhlIG9yZGVyIG9mIG1vbnRocyBzdGFydGluZyBmcm9tIE9jdG9iZXINCm1vbnRoX2xldmVscyA8LSBjKCJPY3RvYmVyIiwgIk5vdmVtYmVyIiwgIkRlY2VtYmVyIiwgIkphbnVhcnkiLCAiRmVicnVhcnkiLCAiTWFyY2giLCAiQXByaWwiLCAiTWF5IiwgIkp1bmUiLCAiSnVseSIsICJBdWd1c3QiLCAiU2VwdGVtYmVyIikNCg0KIyBFbnN1cmUgTW9udGggaXMgYSBmYWN0b3Igd2l0aCB0aGUgY29ycmVjdCBsZXZlbHMNCnBjb2FfZGF0YSRNb250aCA8LSBmYWN0b3IocGNvYV9kYXRhJE1vbnRoLCBsZXZlbHMgPSBtb250aF9sZXZlbHMpDQpwY29hX2RhdGFfcGF0aHdheSA8LSBwY29hX2RhdGFbb3JkZXIocGNvYV9kYXRhJEluZGl2aWR1YWwsIHBjb2FfZGF0YSRNb250aCksIF0NCnBjb2FfZGF0YV9wYXRod2F5JFBDbzFfZGlmZiA8LSBhdmUocGNvYV9kYXRhX3BhdGh3YXkkUENvMSwgcGNvYV9kYXRhX3BhdGh3YXkkSW5kaXZpZHVhbCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTj1mdW5jdGlvbih4KSBjKE5BLCBkaWZmKHgpKSkNCiMgUmVjcmVhdGUgdGhlIHBsb3Qgd2l0aCBzaW1wbGlmaWVkIG1vbnRocw0KcF90ZW1wb3JhbF9jbGVhbiA8LSBnZ3Bsb3QocGNvYV9kYXRhLCBhZXMoeD1Nb250aCwgeT1QQ28xLCBjb2xvcj1JbmRpdmlkdWFsLCBncm91cD1JbmRpdmlkdWFsKSkgKw0KICBnZW9tX2xpbmUobGluZXdpZHRoPTEsIGFscGhhPTAuNykgKw0KICBnZW9tX3BvaW50KHNpemU9MykgKw0KICB0aGVtZV9idygpICsNCiAgbGFicyh4PSIiLCANCiAgICAgICB5PSJQQ28xIiwNCiAgICAgICB0aXRsZT0iVGVtcG9yYWwgQ2hhbmdlcyBpbiBHdXQgTWljcm9iaW9tZSBQVyIpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwNCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgcGFuZWwuc3BhY2luZyA9IHVuaXQoMiwgImxpbmVzIiksDQogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0id2hpdGUiKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSkgKw0KICBmYWNldF93cmFwKH5JbmRpdmlkdWFsLCBzY2FsZXM9ImZyZWVfeSIsIG5jb2w9MikNCg0KIyBQcmludCB0aGUgcGxvdA0KcHJpbnQocF90ZW1wb3JhbF9jbGVhbikNCg0KIyBDYWxjdWxhdGUgbW9udGhseSBzdGF0aXN0aWNzIGZvciBlYWNoIGluZGl2aWR1YWwNCm1vbnRobHlfc3RhdHMgPC0gYWdncmVnYXRlKFBDbzEgfiBNb250aCArIEluZGl2aWR1YWwsIGRhdGE9cGNvYV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgIEZVTj1mdW5jdGlvbih4KSBjKG1lYW49bWVhbih4KSwgc2Q9c2QoeCksIG49bGVuZ3RoKHgpKSkNCg0KIyBDb252ZXJ0IHRoZSByZXN1bHRzIHRvIGEgbW9yZSByZWFkYWJsZSBmb3JtYXQNCm1vbnRobHlfc3RhdHNfZGYgPC0gZGF0YS5mcmFtZSgNCiAgTW9udGggPSBtb250aGx5X3N0YXRzJE1vbnRoLA0KICBJbmRpdmlkdWFsID0gbW9udGhseV9zdGF0cyRJbmRpdmlkdWFsLA0KICBNZWFuX1BDbzEgPSBtb250aGx5X3N0YXRzJFBDbzFbLDFdLA0KICBTRF9QQ28xID0gbW9udGhseV9zdGF0cyRQQ28xWywyXSwNCiAgTl9zYW1wbGVzID0gbW9udGhseV9zdGF0cyRQQ28xWywzXQ0KKQ0KDQpwcmludCgiTW9udGhseSBzdGF0aXN0aWNzIGJ5IGluZGl2aWR1YWw6IikNCnByaW50KG1vbnRobHlfc3RhdHNfZGYpDQoNCiMgU2F2ZSB0aGUgcGxvdA0KDQpnZ3NhdmUoIlRlbXBvcmFsX2NoYW5nZXNfUFdfbW9udGhseS5wZGYiLCBwbG90ID0gcF90ZW1wb3JhbF9jbGVhbiwgd2lkdGggPSA4LCBoZWlnaHQgPSAxMikNCg0KYGBgDQoNCmBgYHtyfQ0KIyBTdW1tYXJpemUgdGhlIG1lYW4gYW5kIFNEIG9mIG1vbnRoLXRvLW1vbnRoIGRpZmZlcmVuY2VzIGZvciBnZW51cyBkYXRhDQpnZW51c19zdW1tYXJ5IDwtIGFnZ3JlZ2F0ZShQQ28xX2RpZmYgfiBJbmRpdmlkdWFsLCBkYXRhPXBjb2FfZGF0YV9nZW51cywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBGVU49ZnVuY3Rpb24oeCkgYyhtZWFuPW1lYW4oYWJzKHgpLCBuYS5ybT1UUlVFKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZD1zZChhYnMoeCksIG5hLnJtPVRSVUUpKSkNCg0KIyBTdW1tYXJpemUgdGhlIG1lYW4gYW5kIFNEIG9mIG1vbnRoLXRvLW1vbnRoIGRpZmZlcmVuY2VzIGZvciBwYXRod2F5IGRhdGENCnBhdGh3YXlfc3VtbWFyeSA8LSBhZ2dyZWdhdGUoUENvMV9kaWZmIH4gSW5kaXZpZHVhbCwgZGF0YT1wY29hX2RhdGFfcGF0aHdheSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTj1mdW5jdGlvbih4KSBjKG1lYW49bWVhbihhYnMoeCksIG5hLnJtPVRSVUUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Q9c2QoYWJzKHgpLCBuYS5ybT1UUlVFKSkpDQoNCmBgYA0KDQpgYGB7cn0NCiMgRXh0cmFjdCBtZWFuIGRpZmZlcmVuY2VzIGZvciBzdGF0aXN0aWNhbCBjb21wYXJpc29uDQpnZW51c19tZWFucyA8LSBzYXBwbHkoZ2VudXNfc3VtbWFyeSRQQ28xX2RpZmYsIGBbYCwgMSkNCnBhdGh3YXlfbWVhbnMgPC0gc2FwcGx5KHBhdGh3YXlfc3VtbWFyeSRQQ28xX2RpZmYsIGBbYCwgMSkNCg0KIyBQZXJmb3JtIGEgcGFpcmVkIHQtdGVzdA0KdF90ZXN0X3Jlc3VsdCA8LSB0LnRlc3QoZ2VudXNfbWVhbnMsIHBhdGh3YXlfbWVhbnMsIHBhaXJlZD1UUlVFKQ0KcHJpbnQodF90ZXN0X3Jlc3VsdCkNCg0KIyBJZiBkYXRhIGlzIG5vdCBub3JtYWxseSBkaXN0cmlidXRlZCwgdXNlIFdpbGNveG9uIHNpZ25lZC1yYW5rIHRlc3QNCndpbGNveF90ZXN0X3Jlc3VsdCA8LSB3aWxjb3gudGVzdChnZW51c19tZWFucywgcGF0aHdheV9tZWFucywgcGFpcmVkPVRSVUUpDQpwcmludCh3aWxjb3hfdGVzdF9yZXN1bHQpDQoNCmBgYA0KDQpgYGB7cn0NCiMgQ29tYmluZSBkYXRhIGZvciB2aXN1YWxpemF0aW9uDQpnZW51c19zdW1tYXJ5JERhdGFzZXQgPC0gIkdlbnVzIg0KcGF0aHdheV9zdW1tYXJ5JERhdGFzZXQgPC0gIlBhdGh3YXkiDQpjb21iaW5lZF9zdW1tYXJ5IDwtIHJiaW5kKGdlbnVzX3N1bW1hcnksIHBhdGh3YXlfc3VtbWFyeSkNCg0KIyBCb3hwbG90IG9mIG1vbnRoLXRvLW1vbnRoIGRpZmZlcmVuY2VzDQpnZ3Bsb3QoY29tYmluZWRfc3VtbWFyeSwgYWVzKHg9RGF0YXNldCwgeT1QQ28xX2RpZmZbLDFdLCBmaWxsPURhdGFzZXQpKSArDQogIGdlb21fYm94cGxvdCgpICsNCiAgbGFicyh4PSJEYXRhc2V0IiwgeT0iTWVhbiBNb250aC10by1Nb250aCBDaGFuZ2UgaW4gUENvMSIsIA0KICAgICAgIHRpdGxlPSJDb21wYXJpc29uIG9mIFRlbXBvcmFsIENoYW5nZXMgaW4gUENvMSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KDQo=